#pragma once
#include "RUDP.h"

/***********************************************************************************************************************/
// package head
//					id					  length	seg count seg id  check			message
// |								|				|		|		|		|   ...    ...   ...
// 0								8				12		14		16		18
/***********************************************************************************************************************/
#define PACKAGE_HEAD_SIZE		18
class RUDPEx :
	public RUDP
{

public:

	RUDPEx();
	virtual ~RUDPEx();

	virtual bool Initialize(const char* ip, uint16_t port);

	virtual void Terminate();

	virtual void Update(uint32_t timeout /* = 0 */);

	virtual void SendTo(uint8_t* buffer, uint32_t len, const char* ip, const uint16_t port, bool reliable);

	virtual void SendTo(uint8_t* buffer, uint32_t len, sockaddr_in* remote, bool reliable);

protected:

	virtual void OnRecvMsg(uint8_t* buffer, uint32_t len, bool reliable, UserData userdata);

private:

	uint64_t AssemblyPackageID(uint16_t lid, uint16_t r, uint32_t ts);

	uint8_t* AssemblyPackageBuffer(uint64_t pid, uint32_t length, uint16_t segCount, uint16_t segID, uint8_t* data, uint32_t dataLen);

	static bool VerifyBuffer(uint8_t* buffer, uint32_t length);

private:

	struct Package
	{
		uint32_t length;
		uint32_t crtLen;
		uint8_t* data;
		uint32_t updatets;
		~Package() { delete[] data; }
	};

	uint16_t pkgID;
	const int segment = BUFF_SIZE - PACKAGE_HEAD_SIZE;

	std::map<uint64_t, Package*> packages;
	uint32_t lastCheckTimeoutTs = 0;
};

